package com.jshop.seckill.service;
import com.Jshop.common.utils.JsonUtils;
import com.Jshop.common.utils.SystemConstants;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jshop.seckill.mapper.SeckillGoodsMapper;
import com.jshop.seckill.pojo.OrderTransfer;
import com.jshop.seckill.pojo.SeckillGoods;
import com.jshop.seckill.pojo.SeckillStatus;
import com.jshop.seckill.pojo.UserInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;


import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service("seckillGoodsService")
public class SeckillGoodsService {

    @Resource
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;


    //MQ
    @Resource
    private RabbitTemplate rabbitmq;

    /**
     * @return java.util.List<com.jshop.seckill.pojo.SeckillGoods>
     * @Description //根据时间段查询秒杀商品
     * @Param [time]
     * @Date 2021/11/13
     **/
    public List<SeckillGoods> list(String time) {
        System.out.println("select key = "+ SystemConstants.SEC_KILL_GOODS_PREFIX + time);
        List<Object> values = redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + time).values();
        List<SeckillGoods> ret = values.stream().map(o -> JsonUtils.parse(o.toString(), SeckillGoods.class)).collect(Collectors.toList());
        return ret;
    }

    /**
     * SeckillGoods条件+分页查询
     */
    public PageInfo<SeckillGoods> findPage(int page, int size) {
        //分页
        PageHelper.startPage(page, size);
        //执行搜索
        return new PageInfo<SeckillGoods>(seckillGoodsMapper.selectAll());
    }


    public void update(SeckillGoods seckillGoods) {
        seckillGoodsMapper.updateByPrimaryKey(seckillGoods);
    }

    /**
     * @Description 添加秒杀商品
     **/
    public void add(SeckillGoods seckillGoods) {
        seckillGoodsMapper.insert(seckillGoods);
    }


    /**
     * @Description 秒杀下单
     * 异步队列发送
     * 用户是否重复抢单
     **/
    public Boolean add(Long id, String time, UserInfo user){



        String goodStr = redisTemplate.boundHashOps("SeckillGoods_" + "2021121016").get("7").toString();
        if (StringUtils.isBlank(goodStr)){
            return false;
        }
        SeckillGoods good = JsonUtils.parse(goodStr, SeckillGoods.class);
        System.out.println("下单商品："+ good);

        //排队抢单
        //String类型 防止Hash大Key问题

        //清除时机在用户支付之后
//        BoundValueOperations<String, String> redisForString = redisTemplate.boundValueOps("SecKill_" + time + id.toString() + "chenxujun");
//        if (redisForString.increment(1L) > 1L){
//            //这里
//        SeckillStatus seckillStatus = new SeckillStatus();
//        seckillStatus.setStatus(3);
//        BoundValueOperations<String, String> killStateRedis = redisTemplate.boundValueOps("SecKill_" + time + id.toString() + "chenxujun_" + "SecKillState");
//            throw new RuntimeException("用户重复抢单");
//        }
//        //两个小时后过期
//        redisForString.expire(1, TimeUnit.HOURS);


        //抢单状态初始化 在订单服务消费到秒杀请求时 更新抢单状态 前端会轮询抢单信息
        SeckillStatus seckillStatus = new SeckillStatus();
        seckillStatus.setStatus(1);
        BoundValueOperations<String, String> killStateRedis = redisTemplate.boundValueOps("SecKill_" + time + id.toString() + "chenxujun_" + "SecKillState");
        killStateRedis.set(JsonUtils.serialize(seckillStatus));
        //两个小时后过期
        killStateRedis.expire(1, TimeUnit.HOURS);

        //


        //异步 延时消息队列发送 注意这里是一层削峰
        //也可以认作是抢单排队的替代动作 消息队列排队 订单服务消费
        OrderTransfer orderTransfer = new OrderTransfer("chenxujun", id, time, 1001L, good);
        //由MQ转移到订单服务
        System.out.println("秒杀商品数据 == " + good);
        rabbitmq.convertAndSend("secKillExchange", "secKillOrder", JsonUtils.serialize(orderTransfer));

        return true;
    }
}

